// import axios from 'axios'
const axios = require('axios')
const { isFunction, merge, cloneDeep } = require('lodash')
// import axiosCancel from './cancel'
const { axiosCancel } = require('./cancel')

class Axios {
    // 用来保存 axios 实例
    axiosInstance = null
    config = null;
    options = null;
    constructor(config) {
        this.config = config;
        this.options = config.requestOptions;
        // 创建 axios 实例 并传入默认配置
        this.axiosInstance = axios.create(config);
        // 调用拦截器
        this.setupInterceptors()
    }
    /**
     * @description 设置拦截器
     */
    setupInterceptors() {
        const {
            requestInterceptorsHook,
            requestInterceptorsCatchHook,
            responseInterceptorsHook,
            responseInterceptorsCatchHook
        } = this.config.axiosHooks
        // 请求拦截器
        this.axiosInstance.interceptors.request.use(
            (config) => {
                // 添加取消请求机制
                this.addCancelToken(config)
                if (isFunction(requestInterceptorsHook)) {
                    config = requestInterceptorsHook(config)
                }
                return config
            },
            (err) => {
                if (isFunction(requestInterceptorsCatchHook)) {
                    requestInterceptorsCatchHook(err)
                }
                return err
            }
        )
        // 响应拦截器
        this.axiosInstance.interceptors.response.use(
            (response) => {
                this.removeCancelToken(response.config.url)
                if (isFunction(responseInterceptorsHook)) {
                    response = responseInterceptorsHook(response)
                }
                return response
            },
            (err) => {
                if (isFunction(responseInterceptorsCatchHook)) {
                    responseInterceptorsCatchHook(err)
                    // 根据具体情况判断
                    if (true || err.code) {
                        return new Promise((resolve) => setTimeout(resolve, 500)).then(() =>
                            this.retryRequest(err)
                        )
                    }
                }
            }
        )
    }

    /**
     * @description 添加 取消请求机制
    */
    addCancelToken(config) {
        // 读取配置 -- 是否忽略取消请求配置
        const { ignoreCancelToken } = config.requestOptions;
        if (!ignoreCancelToken) {
            // 添加请求忽略机制
            !ignoreCancelToken && axiosCancel.add(config)
        }
    }
    /**
     * @description 移除CancelToken
     */
    removeCancelToken(url) {
        axiosCancel.remove(url)
    }
    /**
  * @description 重新请求
  */
    retryRequest(error) {
        const config = error.config
        const { retryCount, isOpenRetry } = config.requestOptions
        if (!isOpenRetry || config.method?.toUpperCase() == "POST") {
            return Promise.reject(error)
        }
        config.retryCount = config.retryCount ?? 0

        if (config.retryCount >= retryCount) {
            return Promise.reject(error)
        }
        config.retryCount++

        return this.axiosInstance.request(config)
    }

    /**
     * @description 请求函数
     */
    request(config, options) {
        const opt = merge({}, this.options, options)
        const axioxConfig = {
            ...cloneDeep(config),
            requestOptions: opt
        }
        const { urlPrefix } = opt
        // 拼接请求前缀如api
        if (urlPrefix) {
            axioxConfig.url = `${urlPrefix}${config.url}`
            console.log('url', axioxConfig.url);
        }
        return new Promise((resolve, reject) => {
            this.axiosInstance
                .request(axioxConfig)
                .then((res) => {
                    resolve(res)
                })
                .catch((err) => {
                    reject(err)
                })
        })
    }
    /**
 * @description get请求
 */
    get(config, options) {
        return this.request({ ...config, method: "GET" }, options)
    }
    /**
     * @description post请求
     */
    post(config, options) {
        return this.request({ ...config, method: "POST" }, options)
    }
}

exports.Axios = Axios